package com.jt.www.job.issue;

import com.jt.www.common.service.JobQueryListService;
import com.jt.www.dao.mapper.issue.mapper.IssuePolicyLogEntityMapper;
import com.jt.www.enums.issue.PolicyInterfaceEnum;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.pay.ResBindDetailQo;
import com.jt.www.model.pay.ResBindQo;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.remote.DexClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 *  扫描失败电子保单重新调用dex接口下载
 * @Author xq.wu
 * @Date 10:02 2020/4/3
 * @Param
 * @return
 **/

@Component
@EnableScheduling
public class CheckBindResourceTaskTest implements SchedulingConfigurer {

    public static final Logger log = LoggerFactory.getLogger(CheckBindResourceTaskTest.class);
    //单个服务器出单查询缓存失效时间 因不同的定时任务决定
    private static final long ISSUE_TIME_OUT = 30L;

    //电子保单是否绑定的定时任务 缓存key
    private static final String ISSUE_LOCK_KEY = "EDU_ISSUE_NEW";

    @Autowired
    IssuePolicyLogEntityMapper issuePolicyLogEntityMapper;

    @Autowired
    JobQueryListService jobQueryListService;

    @Autowired
    InsClient insClient;

    @Autowired
    DexClient dexClient;

    //控制定时任务是否启动
    @Value("${jtpf.issue_new.open}")
    private int checkOpen;

    //任务执行周期
    @Value("${jtpf.issue_new.cron}")
    private String cron;// 每隔一分钟执行一次

    //implements SchedulingConfigurer Override Run
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        if (checkOpen != 1) {
            return;
        }
        if (RedisUtil.setLock(ISSUE_LOCK_KEY, "1", ISSUE_TIME_OUT)) {
            Runnable task0 = () -> checkStart();
            Trigger trigger0 = triggerContext -> new CronTrigger(cron).nextExecutionTime(triggerContext);
            taskRegistrar.addTriggerTask(task0, trigger0);
        }
    }

    //查询数据表是否有失败的电子保单列表
    public List<IssuePolicyLogEntity> selectErrorPolicy() {
        Weekend<IssuePolicyLogEntity> weekend = Weekend.of(IssuePolicyLogEntity.class);
        WeekendCriteria<IssuePolicyLogEntity, Object> criteria = weekend.weekendCriteria();
        List<String> statusList = new ArrayList<>();
        statusList.add("1");
        statusList.add("3");
        criteria.andIn(IssuePolicyLogEntity::getStatus, statusList);
        criteria.andLessThan(IssuePolicyLogEntity::getTimes, 6);
        criteria.andEqualTo(IssuePolicyLogEntity::getType, "4");
        List<IssuePolicyLogEntity> errorPolicyList = jobQueryListService.getJobProcessIssuePolicyLogList(weekend);
        return errorPolicyList;
    }

    //call dex return
    public ResponseEntity callDex(String param, String ifCode) {
        ResponseEntity<String> responseEntity = null;
        //获取对应dex接口
        String policyIfCode = PolicyInterfaceEnum.getDexPolicyInterfaceByIfCode(ifCode);
        if(StringUtils.isNotBlank(policyIfCode)){
            // 文件id为空  继续下载
            log.info(DateUtils.getCurrentTime() + "电子保单入参：" + param);
            String seqNo = Long.toString(Math.abs(new Random().nextLong()));
            try {
                responseEntity = dexClient.text("edu", policyIfCode, "1.0", seqNo, param);
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info(DateUtils.getCurrentTime() + "下载电子保单的job,回参：" + responseEntity.getBody() + "," + responseEntity.getStatusCodeValue());
            return responseEntity;
        }
        log.info("出单ifCode : {} ,未配置电子保单接口", ifCode);
        return responseEntity;
    }


    //call dex error
    public void errorHandle(IssuePolicyLogEntity errorPolicyList, int times) {
        log.error("请求下载电子保单失败");
        errorPolicyList.setTimes(times);
        errorPolicyList.setEPolicyId(errorPolicyList.getEPolicyId());
        errorPolicyList.setStatus("3");
        issuePolicyLogEntityMapper.updateByPrimaryKeySelective(errorPolicyList);
    }

    //call dex success
    public void successHandle(ResponseEntity<String> responseEntity, IssuePolicyLogEntity errorPolicyList, int times) {
        String fileId = responseEntity.getBody();
        if (StringUtils.isEmpty(fileId)) {
            log.error("请求下载电子保单失败");
            errorHandle(errorPolicyList, times);
        }
        //判断是否是直接返回文件id
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(fileId);
        if(!isNum.matches()){
            Document doc = DocumentHelper.createDocument();
            try {
                doc = DocumentHelper.parseText(fileId);
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            Element ebodyElement = doc.getRootElement();
            Element data = ebodyElement.element("data");
            if (data == null || "".equals(data)) {
                log.error("请求下载电子保单失败");
                errorHandle(errorPolicyList, times);
            }
            fileId = data.getStringValue();
        }

        errorPolicyList.setEPolicyId(fileId);
        bindresource(errorPolicyList);
    }

    //检查数据库,并执行任务
    private void checkStart() {
        String currentTime = DateUtils.getCurrentTime();
        log.info(currentTime + "CheckBindResourceTask start,检查出单电子保单绑定资源的的任务开始...");
        //查询数据
        List<IssuePolicyLogEntity> errorPolicy = selectErrorPolicy();
        if (errorPolicy != null && errorPolicy.size() > 0) {
            for (IssuePolicyLogEntity errorPolicyList : errorPolicy) {
                String ifCode = errorPolicyList.getIfCode();
                //获取保单是否有id
                String PolicyId = errorPolicyList.getEPolicyId();
                if (StringUtils.isEmpty(PolicyId)) {
                    //获取到列表里面传给dex的参数(组装保险公司参数)
                    String param = errorPolicyList.getParam();
                    int times = errorPolicyList.getTimes() + 1;
                    try {
                        ResponseEntity responseEntity = callDex(param, ifCode);
                        if(responseEntity!=null){
                            if (responseEntity.getStatusCodeValue() != 200) {
                                errorHandle(errorPolicyList, times);
                            } else {
                                successHandle(responseEntity, errorPolicyList, times);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        errorHandle(errorPolicyList, times);
                    }
                } else {
                    bindresource(errorPolicyList);
                }
            }
        }
    }

    //远程绑定电子保单
    private void bindresource(IssuePolicyLogEntity t) {
        ResBindQo resBindQo = null;
        String ePolicyId = t.getEPolicyId();
        int times = t.getTimes() + 1;
        // 继续去绑定资源
        resBindQo = new ResBindQo();
        String applicationFormCode = t.getApplicationFormCode();
        resBindQo.setApplicationFormCode(t.getApplicationFormCode());
        ResBindDetailQo resBindDetailQo = new ResBindDetailQo();
        resBindDetailQo.setBizCodeType("01");
        resBindDetailQo.setResCode("A002");
        resBindDetailQo.setResId(ePolicyId);
        resBindDetailQo.setResName("电子保单、保单影印件");
        List<ResBindDetailQo> list = new ArrayList<>();
        list.add(resBindDetailQo);
        resBindQo.setDetailList(list);
        ResponseEntity<GenericListResponse<Map<String, String>>> genericListResponseResponseEntity = null;
        try {
            genericListResponseResponseEntity = insClient.bindResources(resBindQo);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("调用绑定资源接口出错!{}", e);
        }
        String code;
        //出错时，超时时处理
        if (null == genericListResponseResponseEntity) {
            code = "9999";
        } else {
            GenericListResponse<Map<String, String>> body = genericListResponseResponseEntity.getBody();
            code = body.getCode();
            log.info(DateUtils.getCurrentTime() + "调用绑定资源接口返回结果码" + code + ":" + body.getMsg());
        }
        t.setTimes(times);
        t.setEPolicyId(ePolicyId);
        if (!"0000".equals(code)) {
            t.setStatus("3");
            issuePolicyLogEntityMapper.updateByPrimaryKeySelective(t);
        } else {
            t.setStatus("2");
            issuePolicyLogEntityMapper.updateByPrimaryKeySelective(t);
        }
    }

}
